﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Xml;
using System.ServiceModel;
using System.ServiceModel.Web;
using Tracy.Plugins.DownloadAdapters.ServiceDefinition;
using System.ServiceModel.Channels;
using Tracy.DataModel;
using System.Collections.Specialized;
using Microsoft.Win32;
using System.IO;
using System.Diagnostics;

namespace Tracy.Plugins.DownloadAdapters
{
    public class UTorrentAdapter : IDownloadAdapter
    {
        private string _applicationFullPath;
        bool _available = false;
        private StringDictionary _settings;//Settings of uTorrent Web API
        private StringDictionary _parameters;
        private const string UTORRENT_WEBUI_URL = "http://localhost:8080/gui";
        private string _token;
        private object _lockHelper = new object();
        IUTorrentWebAPI _client;
        
        public UTorrentAdapter()
        {
            CheckRegistry();
            
        }
        public void Init(StringDictionary parameters) {
            _parameters = new StringDictionary();
            foreach (string key in parameters.Keys)
            {
                _parameters.Add(key, parameters[key]);
            }
        }
        private void CheckRegistry()
        {
            RegistryKey regdir = Registry.ClassesRoot.OpenSubKey("Applications", false);
            regdir = regdir.OpenSubKey("uTorrent.exe", false);
            if (regdir != null)
            {
                regdir = regdir.OpenSubKey("shell").OpenSubKey("open").OpenSubKey("command");

                object installPath = regdir.GetValue("");
                if (installPath != null)
                {
                    _applicationFullPath = installPath.ToString();
                    _applicationFullPath = _applicationFullPath.Substring(1, _applicationFullPath.Length - 7);
                    if (File.Exists(_applicationFullPath)) _available = true;
                }
            }
        }

        private void LoadSettings()
        {
            //Load Settings
            _settings = new StringDictionary();
            foreach (Model.UTorrentSettings.Setting s in _client.GetSettings(_token).Settings)
            {
                _settings.Add(s.Name, s.Value);
            }
        }

        private void InitClient(string defaultPath)
        {

            if (IsAvailable())
            {
                if (Process.GetProcessesByName("uTorrent").Length == 0)
                {
                    Process.Start(_applicationFullPath);
                    System.Threading.Thread.Sleep(2000);
                }

                try
                {
                    //Create uTorrent Web API client
                    CustomBinding uTorrentCustomBinding = new CustomBinding(
                        new WebMessageEncodingBindingElement() { ContentTypeMapper = new JsonContentTypeMapper() },
                        new HttpTransportBindingElement() { ManualAddressing = true, AuthenticationScheme = System.Net.AuthenticationSchemes.Basic, Realm = "uTorrent", AllowCookies = true }
                        );
                    WebChannelFactory<IUTorrentWebAPI> factory = new WebChannelFactory<IUTorrentWebAPI>();
                    factory.Endpoint.Address = new EndpointAddress(UTORRENT_WEBUI_URL);
                    factory.Endpoint.Binding = uTorrentCustomBinding;
                    factory.Credentials.UserName.UserName = _parameters["username"];
                    factory.Credentials.UserName.Password = _parameters["password"];
                    _client = factory.CreateChannel();

                    //Store Security Token
                    _token = _client.GetToken().Token;

                    LoadSettings();

                    //Set default folder
                    if (_settings["dir_completed_download"] != defaultPath)
                    {
                        _client.SetSetting("dir_completed_download", defaultPath, _token);
                        _settings["dir_completed_download"] = defaultPath;
                    }
                    if (_settings["dir_active_download_flag"] != "true")
                    {
                        _client.SetSetting("dir_active_download_flag", "true", _token);
                        _settings["dir_active_download_flag"] = "true";
                    }
                    if (_settings["dir_active_download"] != defaultPath)
                    {
                        _client.SetSetting("dir_active_download", defaultPath, _token);
                        _settings["dir_active_download"] = defaultPath;
                    }
                }
                catch
                {
                    _available = false;
                    throw;
                }
            }
        }


        public void Download(Resource res, string defaultPath)
        {
            if (IsResourceTypeSupported(res.GetResourceType()))
            {
                if (_client == null)
                {
                    lock (_lockHelper)
                    {
                        if (_client == null)
                        {
                            InitClient(defaultPath);//TODO:error handling
                        }
                    }
                }
                if (IsAvailable())
                {
                    _client.AddUrl(res.Url, _token);
                }
            }
        }

        public bool IsAvailable()
        {
            return _available;
        }

        public bool IsResourceTypeSupported(string type)
        {
            if (IsAvailable())
            {
                if (type == "BT") return true;
            }
            return false;
        }

        public string[] GetTempFileExts(string type)
        {
            return new string[] { "!ut" };
        }

        public string GetTempDownloadFolder(string preferredFolder)
        {
            return preferredFolder;
        }

        public string GetValidFileName(string fileName)
        {
            if (fileName == null) return null;
            return fileName.Replace("?", "_").Replace("\\", "_").Replace("/", "_").Replace("*", "_").Replace("\"", "_").Replace(":", "_").Replace("<", "_").Replace(">", "_");
        }

    }
}
